In the development of computer technology, various programming paradigms have been developed. Two of these paradigms are imperative programming and declarative programming. Imperative programming entails providing step by step imperative instructions (e.g., set a equal to 2, increment c, call procedure f( )) which are combined by a programmer to solve the problem of interest. Declarative programming entails providing top level information (e.g., a set of logical constraints to be enforced), which can often be specified in a manner that more transparently relates to the problem of interest. Imperative programming tends to provide improved execution performance, but imperative programs can be very complex and difficult to develop and maintain. Declarative programs tend to be relatively easy to develop and maintain, but declarative programming also tends to provide relatively poor and/or limited execution performance (e.g., slow execution and/or not generally applicable). These relative pros and cons of the imperative and declarative paradigms are well known in the art.
Because the underlying hardware model of a computer is imperative, with the processor(s) executing imperative instructions on passive memory, the earliest programming languages (e.g., assembly language) were imperative, and many of the languages in wide use today (e.g., C, C++) are still largely imperative. At this time, declarative languages (e.g., Prolog, Haskell, Siri and ThingLab) tend to be research languages as opposed to commercial development languages.
In practice, computer languages can include elements of both imperative and declarative paradigms, although the classification of any particular language as primarily imperative or primarily declarative is rarely in doubt. For example, C++ provides classes, virtual functions, and inheritance, which allow a single piece of code to operate on various object types while only being expressed in terms of some base class of these types. This is a declarative aspect of C++, but the C++ language itself is primarily imperative.
Although purely declarative languages have not demonstrated general applicability, impressive results have been obtained in restricted domains. For example, SQL is a restricted-domain declarative language relating to query and update of relational databases. For example, a query is specified by the properties that define a “hit”, as opposed to an imperative specification of how to locate such records. SQL is in wide commercial use for database applications. Another limited domain language is JavaFX, which includes an SQL-like trigger mechanism to declare a procedure to be called when a value changes. This facility is apparently restricted to only allowing the definition of triggers on a data element within the current context. These JavaFX triggers are also similar to the “join points” in AspectJ and other so-called aspect-oriented programming languages. These join points allow code to be invoked at the start and end of procedures, during object initialization, field read and write and exception handlers.
Another example of a restricted domain declarative language is that used to specify a grammar to a parser generator. The grammar is specified as declarative production rules. The parser generator translates a program as a set of these production rules into imperative code that implements a parser for the specified grammar. It is clearly declarative in specifying the grammar to recognize, relying on the language translator to determine how to implement the parser. This declarative approach has proven to have significant value in the generation of language translators, avoiding the time-consuming and error prone task of implementing a parser manually. However, the rest of the compiler or interpreter is implemented in a separate imperative programming language, leading to problems associated with using the two different languages and translators together.
The beneficial results provided by declarative programming in certain circumstances have motivated various attempts to provide the main benefits of both paradigms in a single, general purpose programming language. Approaches to date have largely focused on mapping imperative programming constructs into a declarative model (e.g., a run-time constraint solver, as in Kaleidoscope'90). Another example is the Turtle library for C++, where the constraint model of the Turtle language is incorporated into C++. However, such approaches do not appear capable of addressing the inherent inefficiency of a purely declarative programming model.
Accordingly, it would be an advance in the art to provide for general purpose programming making more efficient and systematic use of both imperative and declarative constructs.